import json
import os
import shutil
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from threading import Timer
import logging
import time
import psutil
import threading

log_file = os.path.join(os.getcwd(), "background_script.log")
logging.basicConfig(level=logging.INFO, filename=log_file, filemode='a',
                        format='%(asctime)s - %(levelname)s - %(message)s')

def is_program_running(program_name):
    """
    Check if a program with the given name is running.
    """
    for proc in psutil.process_iter(attrs=['name', 'cmdline']):
        try:
            if program_name in proc.info['name'] :
                logging.warning(f"Program '{program_name}' is already running with PID {proc.pid}.")
                return True
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue
    return False

class SyncHandler(FileSystemEventHandler):
    def __init__(self, source_dir, dest_dir, debounce_interval):
        self.source_dir = source_dir
        self.dest_dir = dest_dir
        self.debounce_interval = debounce_interval
        self.pending_changes = set()
        self.timer = None

    def on_any_event(self, event):
        # Add changed paths to the pending_changes set
        if event.src_path.startswith(self.source_dir):
            self.pending_changes.add(event.src_path)
        self.schedule_sync()

    def schedule_sync(self):
        if self.timer:
            self.timer.cancel()
        self.timer = Timer(self.debounce_interval, self.sync_changes)
        self.timer.start()

    def sync_changes(self):
        while self.pending_changes:
            src_path = self.pending_changes.pop()
            dest_path = src_path.replace(self.source_dir, self.dest_dir, 1)
            try:
                if os.path.isdir(src_path):
                    os.makedirs(dest_path, exist_ok=True)
                elif os.path.isfile(src_path):
                    shutil.copy2(src_path, dest_path)
                elif not os.path.exists(src_path):
                    if os.path.isdir(dest_path):
                        shutil.rmtree(dest_path)
                    elif os.path.isfile(dest_path):
                        os.remove(dest_path)
                print(f"Synced: {src_path} -> {dest_path}")
            except Exception as e:
                print(f"Error syncing {src_path}: {e}")

def load_config(config_path):
    with open(config_path, "r") as f:
        return json.load(f)
    
def monitor_directory(source, destination,interval):
    observer = Observer()
    event_handler = SyncHandler(source, destination,interval)
    observer.schedule(event_handler, path=source, recursive=True)
    observer.start()
    
    logging.info(f"Watching directory '{source}' -> '{destination}' for changes...")

    try:
        while True:
            time.sleep(1)
            pass
    except KeyboardInterrupt:
        logging.info("Script stopped.")
        observer.stop()
        observer.join()
    except Exception as e:
        logging.error(f"An error occurred: {e}")
    finally:
        logging.info("Script exited.")

def main():
    # script_name = sys.argv[0]
    # script_name = script_name.split("\\")[-1]
    # logging.info(f"'{script_name}' is running")
    # if is_program_running(script_name):
    #     logging.warn(f"'{script_name}' is already running. Not starting again.")
    #     return
    config = load_config("config.json")
    threads = []

    print("Watching directories for changes...")

    for dir_config in config["directories"]:
        source = dir_config["source"]
        destination = dir_config["destination"]
        interval = dir_config["interval"]
        thread = threading.Thread(target=monitor_directory, args=(source,destination,interval))
        thread.start()
        threads.append(thread)

    for thread in threads:
        thread.join()

        


if __name__ == "__main__":
    main()